#include "CPlayer.hpp"
#include "COperation.hpp"
#include "Datas.hpp"
#include "Utils.hpp"

#include <iostream>
#include <algorithm>
#include <functional>
#include <cassert>
#include <exception>

////////////////////////////////////////////////////////////////
// CPlayer
//
/**
* @brief Constructor
*/
CPlayer::CPlayer()
{
	static uint s_id;
	id = s_id++;
}

/**
* @brief Add mob to player
*
* @warning Existing operations must release after it's called.
* (all operations are going to release after it execute.
* So this function should be called in beginning of cycle.)
*
* @param type a type of mob (type id)
* @param pos position to put as default.
*/
void CPlayer::addMob(CMob* newed_instance)
{
	assert(newed_instance != NULL);
	newed_instance->pPlayer = this;
	Mobs.push_back(newed_instance);
}

/// Print player's info inclusive of mobs.
void CPlayer::print() const
{
	using namespace std;
	cout << "Player(" << getId() << ") Data" << endl
		<< "    Is cpu : " << iscpu << endl;
	
//	for_each(Mobs.begin(), Mobs.end(), 
//		mem_fun( &CMob::print ));
}

////////////////////////////////////////////////////////////////
// CPlayers
//
/**
* @brief Constructor
*/
CPlayers::CPlayers()
{
}

/**
* @brief Destructor
*/
CPlayers::~CPlayers()
{
}

/**
* @brief Add player to game.
*
* @return Index num of player
*/
void CPlayers::addPlayer(CPlayer* newed_instance)
{
	this->push_back(newed_instance);
}

/// Print all of players
void CPlayers::print()
{
	foreach<CPlayer>(std::mem_fun(&CPlayer::print));
}

////////////////////////////////////////////////////////////////
// CMob
//
/**
* @brief Constructor
*
* @param player Pointer to CPlayer
* @param type_id Type ID
* @param position Position
*/
CMob::CMob(uint type_id, position_t position)
	: type(type_id)
	, pos(position)
{
	assert(type < Datas::GetShipInfosSize());
	static uint s_id = 0;
	
	life = Datas::ShipInfos[type].life;
	id = s_id++;
}

/**
* @brief Add an operation to the Mob
*
* @param newed_instance A new operation
*/
void CMob::addOperation(Operations::IOperation* newed_instance)
{
	assert(newed_instance != NULL);
	newed_instance->pMob = this;
	Ops.push_back(newed_instance);
}

/**
* @brief Damage to mob
*
* @param value Points of attack
*
* @return If life is negative, return true.
*/
bool CMob::damage(uint value)
{
	life -= value;
	return isDead();
}

/**
* @brief Remove from index and delete memory.
*/
void CMob::remove()
{
	this->pPlayer->Mobs.remove(this);
}

/**
* @brief Interface of iterating (See CPlayers::foreach())
*/
CMob::Container CMob::getParent()
{
	return &CPlayer::Mobs;
}

/// Print Mob's info
void CMob::print() const
{
	using namespace std;

	cout << "Mob(" << pPlayer->getId() << ") Data" << endl
		<< "\tType: " << type << endl
		<< "\tLife: " << life << "/"
			<< Datas::ShipInfos[type].life << endl
		<< "\tPos:" << pos << endl;

	// operation
//	for_each(mobs.begin(), mobs.end(),
//		mem_fun( &COperation::print ));
}


